<template>
  <div class="tree-node">
    <div class="node-header" @click="toggleExpand">
      <span v-if="isExpandable" class="expand-icon">
        <el-icon v-if="expanded">
          <ArrowDown />
        </el-icon>
        <el-icon v-else>
          <ArrowRight />
        </el-icon>
      </span>
      <span v-else class="expand-placeholder"></span>
      
      <span class="node-key">{{ data.key }}:</span>
      
      <span v-if="!isExpandable" class="node-value" :class="valueTypeClass">
        {{ displayValue }}
      </span>
      
      <span v-if="isExpandable" class="node-summary">
        {{ summaryText }}
      </span>
    </div>
    
    <div v-if="expanded && isExpandable" class="node-children">
      <TreeNode
        v-for="(child, index) in data.value"
        :key="index"
        :data="child"
        :expanded="child.expanded"
        @update-value="handleChildUpdate"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { ArrowDown, ArrowRight } from '@element-plus/icons-vue'

// 递归引用自身组件
import TreeNode from './TreeNode.vue'

// 定义组件属性
const props = defineProps({
  data: {
    type: Object,
    required: true
  },
  expanded: {
    type: Boolean,
    default: false
  }
})

// 定义事件
const emit = defineEmits<{
  (e: 'updateValue', path: string, value: any): void
}>()

// 响应式数据
const expanded = ref(props.expanded)

// 计算属性
const isExpandable = computed(() => {
  return props.data.type === 'object' || props.data.type === 'array'
})

const displayValue = computed(() => {
  if (props.data.type === 'string') {
    return `"${props.data.value}"`
  }
  if (props.data.type === 'null') {
    return 'null'
  }
  return String(props.data.value)
})

const valueTypeClass = computed(() => {
  return `value-${props.data.type}`
})

const summaryText = computed(() => {
  if (props.data.type === 'object') {
    const count = props.data.value ? props.data.value.length : 0
    return `{${count} 项}`
  }
  if (props.data.type === 'array') {
    const count = props.data.value ? props.data.value.length : 0
    return `[${count} 项]`
  }
  return ''
})

// 方法
const toggleExpand = () => {
  if (isExpandable.value) {
    expanded.value = !expanded.value
  }
}

const handleChildUpdate = (path: string, value: any) => {
  emit('updateValue', path, value)
}
</script>

<style scoped>
.tree-node {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.node-header {
  padding: 2px 0;
  cursor: pointer;
  display: flex;
  align-items: flex-start;
}

.node-header:hover {
  background-color: #f0f0f0;
}

.expand-icon {
  width: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #c0c4cc;
}

.expand-placeholder {
  width: 20px;
  display: inline-block;
}

.node-key {
  color: #92278f;
  margin-right: 5px;
}

.node-value {
  color: #000;
}

.node-value.value-string {
  color: #c41a16;
}

.node-value.value-number {
  color: #1c00cf;
}

.node-value.value-boolean {
  color: #aa0d91;
}

.node-value.value-null {
  color: #aa0d91;
}

.node-summary {
  color: #666;
}

.node-children {
  padding-left: 20px;
}
</style>